import {
  IsString,
  IsOptional,
  IsEnum,
  IsBoolean,
  IsArray,
  IsUUID,
  IsInt,
  IsUrl,
  MinLength,
  MaxLength,
  Min,
  Max,
  ValidateNested,
  ArrayMinSize,
  ArrayMaxSize
} from 'class-validator'
import { Type, Transform, Expose } from 'class-transformer'
import { ApiProperty, ApiPropertyOptional, PartialType } from '@nestjs/swagger'
import { BaseDto, PaginationDto } from './base.dto'
import { IsValidSlug, IsValidColor } from '../validators/custom.validator'

/**
 * 分类状态枚举
 */
export enum CategoryStatus {
  ACTIVE = 'active',
  INACTIVE = 'inactive',
  HIDDEN = 'hidden'
}

/**
 * 分类类型枚举
 */
export enum CategoryType {
  CONTENT = 'content',
  PRODUCT = 'product',
  TAG = 'tag',
  CUSTOM = 'custom'
}

/**
 * 创建分类DTO
 */
export class CreateCategoryDto {
  @ApiProperty({ description: '分类名称' })
  @IsString()
  @MinLength(1)
  @MaxLength(100)
  name: string

  @ApiPropertyOptional({ description: '分类描述' })
  @IsOptional()
  @IsString()
  @MaxLength(500)
  description?: string

  @ApiPropertyOptional({ description: '分类别名/URL路径' })
  @IsOptional()
  @IsString()
  @IsValidSlug()
  @MaxLength(100)
  slug?: string

  @ApiPropertyOptional({ description: '父分类ID' })
  @IsOptional()
  @IsUUID()
  parentId?: string

  @ApiProperty({
    description: '分类状态',
    enum: CategoryStatus,
    default: CategoryStatus.ACTIVE
  })
  @IsEnum(CategoryStatus)
  status: CategoryStatus = CategoryStatus.ACTIVE

  @ApiProperty({
    description: '分类类型',
    enum: CategoryType,
    default: CategoryType.CONTENT
  })
  @IsEnum(CategoryType)
  type: CategoryType = CategoryType.CONTENT

  @ApiPropertyOptional({ description: '分类图标' })
  @IsOptional()
  @IsString()
  @MaxLength(50)
  icon?: string

  @ApiPropertyOptional({ description: '分类颜色（十六进制）' })
  @IsOptional()
  @IsString()
  @IsValidColor()
  color?: string

  @ApiPropertyOptional({ description: '分类封面图片' })
  @IsOptional()
  @IsUrl()
  coverImage?: string

  @ApiPropertyOptional({ description: '排序权重' })
  @IsOptional()
  @IsInt()
  @Min(0)
  @Max(9999)
  sortOrder?: number

  @ApiPropertyOptional({ description: '是否在导航中显示' })
  @IsOptional()
  @IsBoolean()
  showInNav?: boolean

  @ApiPropertyOptional({ description: '是否在首页显示' })
  @IsOptional()
  @IsBoolean()
  showInHome?: boolean

  @ApiPropertyOptional({ description: 'SEO标题' })
  @IsOptional()
  @IsString()
  @MaxLength(60)
  seoTitle?: string

  @ApiPropertyOptional({ description: 'SEO描述' })
  @IsOptional()
  @IsString()
  @MaxLength(160)
  seoDescription?: string

  @ApiPropertyOptional({ description: 'SEO关键词' })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  @ArrayMaxSize(10)
  seoKeywords?: string[]

  @ApiPropertyOptional({ description: '自定义字段' })
  @IsOptional()
  customFields?: Record<string, any>

  @ApiPropertyOptional({ description: '模板名称' })
  @IsOptional()
  @IsString()
  @MaxLength(50)
  template?: string

  @ApiPropertyOptional({ description: '访问权限级别' })
  @IsOptional()
  @IsEnum(['public', 'member', 'premium', 'admin'])
  accessLevel?: string

  @ApiPropertyOptional({ description: '最大内容数量限制' })
  @IsOptional()
  @IsInt()
  @Min(0)
  maxContentCount?: number

  @ApiPropertyOptional({ description: '是否允许子分类' })
  @IsOptional()
  @IsBoolean()
  allowChildren?: boolean

  @ApiPropertyOptional({ description: '最大层级深度' })
  @IsOptional()
  @IsInt()
  @Min(1)
  @Max(10)
  maxDepth?: number
}

/**
 * 更新分类DTO
 */
export class UpdateCategoryDto extends PartialType(CreateCategoryDto) {
  @ApiPropertyOptional({ description: '更新原因' })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  updateReason?: string
}

/**
 * 查询分类DTO
 */
export class QueryCategoryDto extends PaginationDto {
  @ApiPropertyOptional({ description: '搜索关键词' })
  @IsOptional()
  @IsString()
  @MaxLength(100)
  search?: string = ''

  @ApiPropertyOptional({
    description: '分类状态',
    enum: CategoryStatus
  })
  @IsOptional()
  @IsEnum(CategoryStatus)
  status?: CategoryStatus

  @ApiPropertyOptional({
    description: '分类类型',
    enum: CategoryType
  })
  @IsOptional()
  @IsEnum(CategoryType)
  type?: CategoryType

  @ApiPropertyOptional({ description: '父分类ID' })
  @IsOptional()
  @IsUUID()
  parentId?: string

  @ApiPropertyOptional({ description: '是否只查询根分类' })
  @IsOptional()
  @Transform(({ value }) => value === 'true')
  @IsBoolean()
  rootOnly?: boolean

  @ApiPropertyOptional({ description: '是否包含子分类' })
  @IsOptional()
  @Transform(({ value }) => value === 'true')
  @IsBoolean()
  includeChildren?: boolean

  @ApiPropertyOptional({ description: '是否在导航中显示' })
  @IsOptional()
  @Transform(({ value }) => value === 'true')
  @IsBoolean()
  showInNav?: boolean

  @ApiPropertyOptional({ description: '是否在首页显示' })
  @IsOptional()
  @Transform(({ value }) => value === 'true')
  @IsBoolean()
  showInHome?: boolean

  @ApiPropertyOptional({ description: '最大层级深度' })
  @IsOptional()
  @Transform(({ value }) => parseInt(value))
  @IsInt()
  @Min(1)
  @Max(10)
  maxDepth?: number

  @ApiPropertyOptional({ description: '最小内容数量' })
  @IsOptional()
  @Transform(({ value }) => parseInt(value))
  @IsInt()
  @Min(0)
  minContentCount?: number

  @ApiPropertyOptional({ description: '最大内容数量' })
  @IsOptional()
  @Transform(({ value }) => parseInt(value))
  @IsInt()
  @Min(0)
  maxContentCount?: number

  @ApiPropertyOptional({ description: '访问权限级别' })
  @IsOptional()
  @IsEnum(['public', 'member', 'premium', 'admin'])
  accessLevel?: string

  @ApiPropertyOptional({ description: '是否包含空分类' })
  @IsOptional()
  @Transform(({ value }) => value === 'true')
  @IsBoolean()
  includeEmpty?: boolean
}

/**
 * 分类响应DTO
 */
export class CategoryResponseDto extends BaseDto {
  @ApiProperty({ description: '分类名称' })
  @Expose()
  name: string

  @ApiPropertyOptional({ description: '分类描述' })
  @Expose()
  description?: string

  @ApiProperty({ description: '分类别名' })
  @Expose()
  slug: string

  @ApiPropertyOptional({ description: '父分类ID' })
  @Expose()
  parentId?: string

  @ApiProperty({ description: '分类状态', enum: CategoryStatus })
  @Expose()
  status: CategoryStatus

  @ApiProperty({ description: '分类类型', enum: CategoryType })
  @Expose()
  type: CategoryType

  @ApiPropertyOptional({ description: '分类图标' })
  @Expose()
  icon?: string

  @ApiPropertyOptional({ description: '分类颜色' })
  @Expose()
  color?: string

  @ApiPropertyOptional({ description: '分类封面图片' })
  @Expose()
  coverImage?: string

  @ApiProperty({ description: '排序权重' })
  @Expose()
  sortOrder: number

  @ApiProperty({ description: '层级深度' })
  @Expose()
  depth: number

  @ApiProperty({ description: '分类路径' })
  @Expose()
  path: string

  @ApiProperty({ description: '完整路径名称' })
  @Expose()
  fullPath: string

  @ApiProperty({ description: '是否在导航中显示' })
  @Expose()
  showInNav: boolean

  @ApiProperty({ description: '是否在首页显示' })
  @Expose()
  showInHome: boolean

  @ApiPropertyOptional({ description: 'SEO标题' })
  @Expose()
  seoTitle?: string

  @ApiPropertyOptional({ description: 'SEO描述' })
  @Expose()
  seoDescription?: string

  @ApiPropertyOptional({ description: 'SEO关键词' })
  @Expose()
  seoKeywords?: string[]

  @ApiProperty({ description: '内容数量' })
  @Expose()
  contentCount: number

  @ApiProperty({ description: '子分类数量' })
  @Expose()
  childrenCount: number

  @ApiProperty({ description: '总内容数量（包含子分类）' })
  @Expose()
  totalContentCount: number

  @ApiPropertyOptional({ description: '父分类信息' })
  @Expose()
  parent?: {
    id: string
    name: string
    slug: string
    path: string
  }

  @ApiPropertyOptional({ description: '子分类列表' })
  @Expose()
  children?: CategoryResponseDto[]

  @ApiPropertyOptional({ description: '祖先分类列表' })
  @Expose()
  ancestors?: Array<{
    id: string
    name: string
    slug: string
    path: string
  }>

  @ApiPropertyOptional({ description: '创建者信息' })
  @Expose()
  creator?: {
    id: string
    username: string
    nickname: string
  }

  @ApiPropertyOptional({ description: '最后更新者信息' })
  @Expose()
  lastEditor?: {
    id: string
    username: string
    nickname: string
  }

  @ApiPropertyOptional({ description: '最后更新时间' })
  @Expose()
  lastEditedAt?: Date

  @ApiPropertyOptional({ description: '自定义字段' })
  @Expose()
  customFields?: Record<string, any>

  @ApiPropertyOptional({ description: '模板名称' })
  @Expose()
  template?: string

  @ApiPropertyOptional({ description: '访问权限级别' })
  @Expose()
  accessLevel?: string

  @ApiPropertyOptional({ description: '最大内容数量限制' })
  @Expose()
  maxContentCount?: number

  @ApiProperty({ description: '是否允许子分类' })
  @Expose()
  allowChildren: boolean

  @ApiPropertyOptional({ description: '最大层级深度' })
  @Expose()
  maxDepth?: number

  @ApiProperty({ description: '是否有子分类' })
  @Expose()
  hasChildren: boolean

  @ApiProperty({ description: '是否为叶子节点' })
  @Expose()
  isLeaf: boolean

  @ApiPropertyOptional({ description: '最近内容' })
  @Expose()
  recentContent?: Array<{
    id: string
    title: string
    slug: string
    createdAt: Date
  }>
}

/**
 * 分类树DTO
 */
export class CategoryTreeDto {
  @ApiProperty({ description: '分类ID' })
  @Expose()
  id: string

  @ApiProperty({ description: '分类名称' })
  @Expose()
  name: string

  @ApiProperty({ description: '分类别名' })
  @Expose()
  slug: string

  @ApiPropertyOptional({ description: '分类描述' })
  @Expose()
  description?: string

  @ApiProperty({ description: '分类状态', enum: CategoryStatus })
  @Expose()
  status: CategoryStatus

  @ApiProperty({ description: '分类类型', enum: CategoryType })
  @Expose()
  type: CategoryType

  @ApiPropertyOptional({ description: '分类图标' })
  @Expose()
  icon?: string

  @ApiPropertyOptional({ description: '分类颜色' })
  @Expose()
  color?: string

  @ApiProperty({ description: '排序权重' })
  @Expose()
  sortOrder: number

  @ApiProperty({ description: '层级深度' })
  @Expose()
  depth: number

  @ApiProperty({ description: '分类路径' })
  @Expose()
  path: string

  @ApiProperty({ description: '内容数量' })
  @Expose()
  contentCount: number

  @ApiProperty({ description: '是否在导航中显示' })
  @Expose()
  showInNav: boolean

  @ApiProperty({ description: '是否在首页显示' })
  @Expose()
  showInHome: boolean

  @ApiPropertyOptional({ description: '子分类列表' })
  @Expose()
  @Type(() => CategoryTreeDto)
  children?: CategoryTreeDto[]

  @ApiProperty({ description: '是否有子分类' })
  @Expose()
  hasChildren: boolean

  @ApiProperty({ description: '是否展开' })
  @Expose()
  expanded?: boolean

  @ApiProperty({ description: '是否可选择' })
  @Expose()
  selectable?: boolean

  @ApiProperty({ description: '是否禁用' })
  @Expose()
  disabled?: boolean
}

/**
 * 分类统计DTO
 */
export class CategoryStatsDto {
  @ApiProperty({ description: '总分类数' })
  @Expose()
  totalCategories: number

  @ApiProperty({ description: '活跃分类数' })
  @Expose()
  activeCategories: number

  @ApiProperty({ description: '隐藏分类数' })
  @Expose()
  hiddenCategories: number

  @ApiProperty({ description: '根分类数' })
  @Expose()
  rootCategories: number

  @ApiProperty({ description: '空分类数（无内容）' })
  @Expose()
  emptyCategories: number

  @ApiProperty({ description: '最大层级深度' })
  @Expose()
  maxDepth: number

  @ApiProperty({ description: '平均层级深度' })
  @Expose()
  averageDepth: number

  @ApiProperty({ description: '按类型统计' })
  @Expose()
  byType: Record<CategoryType, number>

  @ApiProperty({ description: '按状态统计' })
  @Expose()
  byStatus: Record<CategoryStatus, number>

  @ApiProperty({ description: '按层级统计' })
  @Expose()
  byDepth: Record<number, number>

  @ApiProperty({ description: '内容最多的分类' })
  @Expose()
  topCategories: Array<{
    id: string
    name: string
    contentCount: number
    totalContentCount: number
  }>

  @ApiProperty({ description: '最近创建的分类' })
  @Expose()
  recentCategories: Array<{
    id: string
    name: string
    createdAt: Date
    contentCount: number
  }>

  @ApiProperty({ description: '最近更新的分类' })
  @Expose()
  recentlyUpdated: Array<{
    id: string
    name: string
    updatedAt: Date
    contentCount: number
  }>
}

/**
 * 批量分类操作DTO
 */
export class BulkCategoryOperationDto {
  @ApiProperty({
    description: '操作类型',
    enum: ['activate', 'deactivate', 'hide', 'delete', 'move', 'update_type', 'update_access']
  })
  @IsEnum(['activate', 'deactivate', 'hide', 'delete', 'move', 'update_type', 'update_access'])
  operation: string

  @ApiProperty({ description: '分类ID列表' })
  @IsArray()
  @IsUUID(4, { each: true })
  @ArrayMinSize(1)
  @ArrayMaxSize(100)
  items: string[]

  @ApiPropertyOptional({ description: '操作参数' })
  @IsOptional()
  params?: {
    parentId?: string
    type?: CategoryType
    accessLevel?: string
    status?: CategoryStatus
    [key: string]: any
  }

  @ApiPropertyOptional({ description: '操作原因' })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  reason?: string
}

/**
 * 分类移动DTO
 */
export class MoveCategoryDto {
  @ApiPropertyOptional({ description: '新父分类ID（null表示移动到根级）' })
  @IsOptional()
  @IsUUID()
  parentId?: string

  @ApiPropertyOptional({ description: '在新位置的排序位置' })
  @IsOptional()
  @IsInt()
  @Min(0)
  position?: number

  @ApiPropertyOptional({ description: '移动原因' })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  reason?: string
}

/**
 * 分类排序DTO
 */
export class SortCategoryDto {
  @ApiProperty({ description: '分类排序列表' })
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => CategorySortItem)
  @ArrayMinSize(1)
  items: CategorySortItem[]

  @ApiPropertyOptional({ description: '排序原因' })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  reason?: string
}

export class CategorySortItem {
  @ApiProperty({ description: '分类ID' })
  @IsUUID()
  id: string

  @ApiProperty({ description: '排序权重' })
  @IsInt()
  @Min(0)
  @Max(9999)
  sortOrder: number

  @ApiPropertyOptional({ description: '父分类ID' })
  @IsOptional()
  @IsUUID()
  parentId?: string
}

/**
 * 分类验证结果DTO
 */
export class CategoryValidationDto {
  @ApiProperty({ description: '是否有效' })
  @Expose()
  isValid: boolean

  @ApiProperty({ description: '验证问题列表' })
  @Expose()
  issues: Array<{
    type: 'circular_reference' | 'invalid_parent' | 'depth_exceeded' | 'duplicate_slug' | 'orphaned_category'
    categoryId: string
    categoryName: string
    message: string
    severity: 'error' | 'warning' | 'info'
  }>

  @ApiProperty({ description: '验证统计' })
  @Expose()
  stats: {
    totalCategories: number
    validCategories: number
    invalidCategories: number
    warnings: number
    errors: number
  }

  @ApiProperty({ description: '修复建议' })
  @Expose()
  suggestions: Array<{
    type: string
    description: string
    action: string
    categoryIds: string[]
  }>
}

/**
 * 分类搜索DTO
 */
export class CategorySearchDto {
  @ApiProperty({ description: '搜索关键词' })
  @IsString()
  @MinLength(1)
  @MaxLength(100)
  query: string

  @ApiPropertyOptional({ description: '分类类型' })
  @IsOptional()
  @IsEnum(CategoryType)
  type?: CategoryType

  @ApiPropertyOptional({ description: '分类状态' })
  @IsOptional()
  @IsEnum(CategoryStatus)
  status?: CategoryStatus

  @ApiPropertyOptional({ description: '搜索范围' })
  @IsOptional()
  @IsArray()
  @IsEnum(['name', 'description', 'slug'], { each: true })
  searchIn?: string[]

  @ApiPropertyOptional({ description: '是否包含子分类' })
  @IsOptional()
  @IsBoolean()
  includeChildren?: boolean

  @ApiPropertyOptional({ description: '最大结果数量' })
  @IsOptional()
  @Transform(({ value }) => parseInt(value))
  @IsInt()
  @Min(1)
  @Max(100)
  limit?: number = 20

  @ApiPropertyOptional({ description: '排序字段' })
  @IsOptional()
  @IsEnum(['name', 'created_at', 'updated_at', 'content_count', 'sort_order'])
  sortBy?: string = 'name'

  @ApiPropertyOptional({ description: '排序方向' })
  @IsOptional()
  @IsEnum(['asc', 'desc'])
  sortOrder?: string = 'asc'
}
